/*
 *    Copyright (c) 2018-2025, proj All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the proj developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: proj
 */

package com.ykht.proj.coupon.controller.c;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ykht.proj.common.core.util.R;
import com.ykht.proj.common.security.annotation.Inner;
import com.ykht.proj.common.security.util.SecurityUtils;
import com.ykht.proj.coupon.entity.CnBrand;
import com.ykht.proj.coupon.entity.CnCoupon;
import com.ykht.proj.coupon.entity.CnCouponLog;
import com.ykht.proj.coupon.entity.CnPerson;
import com.ykht.proj.coupon.service.*;
import com.ykht.proj.coupon.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 优惠券表
 *
 * @author proj code generator
 * @date 2020-11-16 17:00:20
 */
@RestController
@AllArgsConstructor
@RequestMapping("c/coupon")
@Api(value = "cncoupon", tags = "c端优惠券相关")
@Slf4j
public class CouponController {
	/**
	 * 优惠券服务
	 */
	private final CnCouponService cnCouponService;
	private final CnCouponLogService cnCouponLogService;
	/**
	 * 店铺服务
	 */
	private final CnShopService cnShopService;

	@ApiOperation(value = "万券齐发")
	@GetMapping("wqqf")
	public R<Page<WqqfCouponVo>> wqqf(Page<WqqfCouponVo> page, WqqfCoupon req) {
		return R.ok(cnCouponService.wqqf(page,req));
	}
	/**
	 * 通过id查询优惠券表
	 *
	 * @return R
	 */
	@ApiOperation(value = "优惠券详情")
	@PostMapping("detail")
	public R<CnCouponDetailResp> getById(@RequestBody CnCouponDetailReq req) {
		try {
			log.info("->优惠券详情:{}", JSONUtil.toJsonStr(req));
			Long loginId = SecurityUtils.getPersonId();
			CnCoupon cnCoupon = cnCouponService.getById(req.getId());
			CnCouponDetailResp resp = new CnCouponDetailResp();
			CnBrand cnBrand = new CnBrand();
			cnBrand.setId(cnCoupon.getBrandId());
			cnBrand = cnBrand.selectById();
			BeanUtil.copyProperties(cnCoupon, resp);
			resp.setBrandName(cnBrand.getBrandName());
			resp.setLogoUrl(cnBrand.getLogoUrl());

			List<CnCouponLog> logList = cnCouponLogService.list(Wrappers.lambdaQuery(CnCouponLog.class)
					.eq(CnCouponLog::getCouponId, req.getId()).eq(CnCouponLog::getRecipientId, loginId).eq(CnCouponLog::getStatus, 0));//未使用
			resp.setWhetherReceive(logList.size() > 0 ? 1l : 0L);


			//附近门店
			List<CnShopDisVo> list = null;
			if (0 == cnCoupon.getType()) {//全门店
				CnShopDisVo cnShopDisVo = new CnShopDisVo();
				cnShopDisVo.setBrandId(cnCoupon.getBrandId());
				cnShopDisVo.setLatitude(req.getLatitude());
				cnShopDisVo.setLongitude(req.getLongitude());
				list = cnShopService.shopAndDistant(cnShopDisVo);

			} else {//多门店和单门店
				list = cnShopService.shopAndDistant4NotTyCoupon(req.getLatitude(), req.getLongitude(), cnCoupon.getId());
				list = list.stream().filter(oo -> oo != null && oo.getId() != null).collect(Collectors.toList());//过滤门店id不存在的数据
				list.stream().sorted(Comparator.comparing(CnShopDisVo::getDistance).reversed()).collect(Collectors.toList());
			}
			resp.setNum(list.size());
			if (list.size() == 0) return R.ok(resp);
			resp.setShopId(list.get(0).getId());
			resp.setShopName(list.get(0).getName());
			resp.setLongitude(list.get(0).getLongitude());
			resp.setLatitude(list.get(0).getLatitude());
			resp.setAddress(list.get(0).getAddress());
			return R.ok(resp);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

	@ApiOperation(value = "c领取优惠券")
	@GetMapping("/receive/{id}")
	public R receiveCoupon(@PathVariable Long id,Long shareId) {
		try {
			log.info("--------------->c端领取单个个优惠券：id:{},shareId:{}", id, shareId);
			return cnCouponService.receiveCoupon(id, null,shareId);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed("领取优惠券失败");
		}
	}

	@ApiOperation(value = "领取服务员分享的多个优惠券")
	@GetMapping("/receiveByIds")
	public R receiveCouponByIds(@RequestParam("ids") String ids, Long waiterId, Long articleId, Integer addCouponFlag,Long shareId) {
		try {
			log.info("--------------->c端领取的多个优惠券：ids:{},waiterId:{},articleId:{},addCouponFlag:{},shareId:{}", ids, waiterId, articleId, addCouponFlag,shareId);
			return cnCouponService.receiveCouponByIds(ids, waiterId, articleId, addCouponFlag,shareId);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed("领取优惠券失败");
		}
	}


	/**
	 * C端（用户） 领劵中心
	 *
	 * @return
	 */
	@ApiOperation(value = "C端（用户） 领劵中心")
	@GetMapping("/getCouponList")
	public R<Object> getCouponList() {
		try {
			List<CnCouponDetailResp> detailRespList = cnCouponService.getCouponList();
			return R.ok().setData(detailRespList);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

	/**
	 * C端（用户） 领劵中心列表的下拉
	 *
	 * @return
	 */
	@ApiOperation(value = "C端（用户） 领劵中心列表的下拉")
	@PostMapping("/getCouponListPage")
	public R<Object> getCouponListPage(@RequestBody List<Long> ids) {
		try {
			List<CnCouponDetailResp> detailRespList = cnCouponService.getCouponListPage(ids);
			return R.ok().setData(detailRespList);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}


	/**
	 * C端（用户） 首页  爆款优惠========
	 * 爆款优惠：
	 * 排序频次：每隔2小时进行重新排序一次。（即每天的2:00。4:00.   6:00.   8:00     10:00.   12:00.   14:00.   16:00.    18:00.   20:00.  22:00.  24:00等进行重新排序）
	 *
	 * @return
	 */
	@ApiOperation(value = "C端（用户） 首页  爆款优惠")
	@RequestMapping("/getHotCouponList")
	public R<List<CnCouponDetailResp>> getHotCouponList(@RequestBody CnCouponDetailReq req) {

		//0-2一个阶段，2-4一个阶段，以此类推
		LocalDateTime now = LocalDateTime.now();
		//本阶段开始时间
		LocalDateTime start = LocalDateTime.of(LocalDate.now(), LocalTime.of(now.getHour() % 2 == 0 ? now.getHour() : now.getHour() - 1, 0));
		try {
			//所有已领取的优惠券
			List<CnCouponLog> logList = cnCouponLogService.list(Wrappers.lambdaQuery(CnCouponLog.class)
					.eq(CnCouponLog::getRecipientId, SecurityUtils.getPersonId())
					.eq(CnCouponLog::getStatus, 0));//未使用

			//本阶段领取的优惠券
			List<CnCouponLog> nowList = logList.stream().filter(o -> o.getReceiveTime().isAfter(start) && o.getReceiveTime().isBefore(now)).collect(Collectors.toList());
			//当前阶段有领取的，就移除当前
//			if (nowList.size()>0) logList.removeAll(nowList);
			//所有非当前阶段的id
//			List<Long> couIds = logList.stream().map(CnCouponLog::getCouponId).collect(Collectors.toList());
			//所有当前阶段的id
			List<Long> nowCouIds = nowList.stream().map(CnCouponLog::getCouponId).collect(Collectors.toList());
			List<CnCouponDetailResp> respList = new ArrayList<>();
			if (null != req.getLongitude() && null != req.getLatitude()) {

				// 获取通用的优惠券
				List<CnCouponDetailResp> hotCouponList = cnShopService.getCommonCouponList(req.getLongitude(), req.getLatitude(),
						req.getPhone() != null ? SecurityUtils.getPersonId() : null, nowCouIds);
				// 获取多门店的优惠券
				List<CnCouponDetailResp> hotCouponList1 = cnShopService.getMultiStoreCouponList(req.getLongitude(), req.getLatitude(),
						req.getPhone() != null ? SecurityUtils.getPersonId() : null, nowCouIds);
				// 获取单个门店的优惠券
				List<CnCouponDetailResp> hotCouponList2 = cnShopService.getSingleStoreCouponList(req.getLongitude(), req.getLatitude(),
						req.getPhone() != null ? SecurityUtils.getPersonId() : null, nowCouIds);
				hotCouponList.addAll(hotCouponList1);
				hotCouponList.addAll(hotCouponList2);
				// 根据减免金额排序 倒叙
				List<CnCouponDetailResp> collect = hotCouponList.stream().sorted(
						Comparator.comparing(CnCouponDetailResp::getReductionMoney).reversed()).collect(Collectors.toList());
				// 根据排好的顺序 按照品牌分组
				Map<Long, List<CnCouponDetailResp>> listMap = collect.stream().collect(Collectors.groupingBy(CnCouponDetailResp::getBrandId, Collectors.toList()));
				// 获取每组组的第一条数据
				Integer i = 0;
				for (Long aLong : listMap.keySet()) {
					if (6 > i) {
						i++;
						respList.add(listMap.get(aLong).get(0));
					}
				}

				if (respList.size() < 6) {
					// 已获取的品牌ID集合
					List<Long> brandIdList = new ArrayList<>();
					respList.stream().forEach(itme -> brandIdList.add(itme.getBrandId()));
					Integer number = 6 - respList.size();
					List<CnCouponDetailResp> loginWholeHotCouponList = cnCouponService.getLoginWholeHotCouponList(number, brandIdList, req.getPhone() != null ? SecurityUtils.getPersonId() : null, nowCouIds);
//					loginWholeHotCouponList.stream().forEach(itme -> respList.add(itme));
					for (CnCouponDetailResp o : loginWholeHotCouponList) {
						respList.add(o);
					}

				}
				if (req.getPhone() == null) {
					respList.stream().forEach(itme -> itme.setWhetherReceive(null));
				}
			} else if (req.getPhone() != null) {
				respList = cnCouponService.getLoginWholeHotCouponList(6, new ArrayList<>(), SecurityUtils.getPersonId(), nowCouIds);
			} else {
				respList = cnCouponService.getWholeHotCouponList(6);
				respList.stream().forEach(itme -> itme.setWhetherReceive(null));
			}
			respList.stream().forEach(o -> o.setWhetherReceive(nowCouIds.contains(o.getId()) ? 0l : 1L));
			return R.ok(respList);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

}
